# subtitles_wr.py：字幕生成、查看、修改
#
# 1. 字幕生成暂时使用剪映
# 2. 对指定路径的所有视频进行字幕生成，路径在命令行输入

# 待实现：
# -检索指定路径下的所有mp4和srt文件
# -如果当前子文件夹有多个视频，为每一个视频再创立一个单独的文件夹，名字和视频一致，存放视频和对应的字幕
# -判断当前mp4是否有srt字幕，如果有则不导出
# -调用剪映只导出srt字幕文件
# -转换字幕是否完成由获取转换种某个点的颜色确认
# -字幕文件命名和位置和mp4一样
# -字幕文件保存
# 多机测试及坐标标定
# 转换路径使用命令行输入

# 需要修改的全局变量或配置：
# 文件检索路径 mp4_file_path
# 剪映软件路径 jianying_exe_path
# pc平台 PC_COM 据此进行坐标的标正
#
#

import smtplib
import eyed3
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from pydub import AudioSegment
import email
import imaplib
import os
import shutil
import time
import traceback
import zipfile
from email.header import decode_header, Header
from email.utils import parseaddr
from pathlib import Path
import datetime
import pyautogui
import pyperclip
from moviepy.editor import VideoFileClip

DEBUG = 1
PC_COM = 1  # 0-家庭 1-公司

mp4_file_path = "D:\\video\\video_temp"  # 文件检索路径
if PC_COM == 1:
    jianying_exe_path = '"C:\\Users\\addoi\\AppData\\Local\\JianyingPro\\Apps\\JianyingPro.exe"'
else:
    jianying_exe_path = '"D:\\Program Files\\JianyingPro\\JianyingPro.exe"'


rewrite_print = print
def print(*arg):
   rewrite_print(*arg)
   output_dir = "log_file"
   if not os.path.exists(output_dir):
         os.makedirs(output_dir)
   log_name = 'log.txt' # 日志文件名称
   filename = os.path.join(output_dir, log_name)
   rewrite_print(*arg,file=open(filename,"a")) # 写入文件

def print_d(*arg): #仿真调试用
    if DEBUG == 1:
        print('------调试打印开始-----')
        print(*arg)
        print('------调试打印结束-----\r\n')


class doc_function():  # 文件操作
    def save_data_txt(data):  # 添加数据到文件
        info_str = str(data)
        info_str += '\r\n'
        print(info_str)
        with open('flash_tool.log', 'a') as lead:
            lead.write(info_str)

    def set_data(data):  # 重写文件
        data_w = "data  " + data
        fi = open('data.txt', 'w', encoding='utf-8')
        fi.write(data_w)

    def mkdir(path):  # 新建文件夹
        folder = os.path.exists(path)

        if not folder:  # 判断是否存在文件夹如果不存在则创建为文件夹
            os.makedirs(path)  # makedirs 创建文件时如果路径不存在会创建这个路径
            print("---  new folder...  ---")
        else:
            print("folder is:", path)

    def copyfile(srcfile, dstpath):  # 复制文件
        if not os.path.isfile(srcfile):
            print("%s not exist!" % (srcfile))
        else:
            fpath, fname = os.path.split(srcfile)  # 分离文件名和路径
            if not os.path.exists(dstpath):
                os.makedirs(dstpath)  # 创建路径
            shutil.copy(srcfile, dstpath + fname)  # 复制文件

    def remove_file(old_path, new_path):  # 移动文件夹下所有文件到另一个文件夹
        filelist = os.listdir(old_path)  # 列出该目录下的所有文件,listdir返回的文件列表是不包含路径的。
        # print(filelist)
        for file in filelist:
            src = os.path.join(old_path, file)
            dst = os.path.join(new_path, file)
            # print('src:', src)  # 原文件路径下的文件
            # print('dst:', dst)  # 移动到新的路径下的文件
            shutil.move(src, dst)

    def file_zip(start_file, zip_dir):  # 压缩文件
        # start_dir 要压缩的文件
        # zip_file 输出zip文件的路径
        fpath_start_dir, fname = os.path.split(start_file)  # 分离文件名和路径

        zip_file = zip_dir + '.zip'
        z = zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED)
        print(z)
        for path, dirname, file_name in os.walk(fpath_start_dir):
            # print("文件夹根路径：", path)
            fpath = path.replace(fpath_start_dir, '')  # 去除根路径名称
            # print("--去除根路径：", fpath)
            fpath = fpath and fpath + os.sep  # 在原fpath加上\
            # print("****去除根路径+\ ：", fpath)

            for filename in file_name:  # 逐个循环读取文档名称
                if filename.find(fname) >= 0:
                    # print(filename)
                    z.write(os.path.join(path, filename), fpath + filename)  # 实现在输出路径的Zip压缩操作
        z.close()


    # def get_web():
        # if os.path.isfile("cfg.txt"):
        #     f = open(r"cfg.txt", "r", encoding="utf-8")
        #     data = f.read()
        #     reg = 'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
        #     url = re.findall(reg, data)
        #     return url[-1]  # 假如地址在这一行的最后一个位置
        # else:
        #     print(" cfg.txt is not accessible, please creat!!!")
        #     sys.exit()

    def file_unzip_download(unzip_file):
        print(f"开始进行解压缩并下载···")

        zip_file = zipfile.ZipFile(unzip_file)
        fpath, fname = os.path.split(unzip_file)
        out_file = fpath + "\\unzip"
        if os.path.isdir(out_file):
            shutil.rmtree(out_file)
            os.mkdir(out_file)
        else:
            os.mkdir(out_file)
        for names in zip_file.namelist():
            zip_file.extract(names, out_file)
        zip_file.close()
        folder = Path(out_file.strip())
        result = list(folder.rglob(f'*{".hex"}*'))  # 只要hex文件
        print(result[0])  # 默认一个压缩包只有一个文件
        flash_file = str(result[0])
        # 进行文件的各种操作处理
        shutil.rmtree(out_file)

    def search_file(key_word, self_path=None):  # 查找的关键字 self_path是自定义路径
        # folder_str = os.path.join(os.getcwd(), qq_email_rx.Subject)  # 刘森 新世界
        if self_path != None:
            folder_str = self_path

        folder = Path(folder_str.strip())
        print(folder)
        if folder.exists():
            print("开始根据关键字查找文件···")
        else:
            print("未找到存放关键字对应文件的文件夹")
            return None

        result = list(folder.rglob(f'*{key_word}*'))
        if not result:
            print(f'在{folder} 下未找到关键字名称 {key_word} 的文件夹或文件')
            return None
        else:
            print(f'在{folder} 下找到关键字名称 {key_word} 的文件夹或文件{result}')
            return result

    def sort_build_path(check_path = mp4_file_path):  # 归类 为单独的视频创建独立子文件夹
        mp4_path_list = doc_function.search_file(".mp4", check_path)

        for mp4 in mp4_path_list:
            f_mp4_path, f_mp4_name = os.path.split(mp4)
            f_mp4_name = f_mp4_name[:-4]
            len_name = len(f_mp4_name)
            if f_mp4_path[(len(f_mp4_path) - len_name):] != f_mp4_name: # 上一级路径名字和视频名字不一样 则新建文件夹
                build_path = f_mp4_path + "\\" + f_mp4_name
                doc_function.mkdir(build_path)
                doc_function.copyfile(mp4, build_path + "\\") # 将文件移动到新建文件夹
                os.remove(mp4)


    def search_no_srt_mp4(check_path = mp4_file_path): # 查找没有字幕文件的mp4路径
        mp4_path_list = doc_function.search_file(".mp4", check_path)
        srt_path_list = doc_function.search_file(".srt", check_path)
        mp4_srt_path_list = mp4_path_list

        if srt_path_list != None:
            for srt in srt_path_list:
                f_srt_path, f_srt_name = os.path.split(srt)

                for mp4 in mp4_path_list:
                    f_mp4_path, f_mp4_name = os.path.split(mp4)
                    if f_mp4_name[:-4] == f_srt_name[:-4]:
                        mp4_srt_path_list.remove(mp4)
                        break

            print("查找到的没有srt的mp4文件路径列表：")
            for mp4 in mp4_srt_path_list:
                print(mp4)
        else:
            print("没有找到srt文件")

        return mp4_srt_path_list


    def get_str_row_column(words): #获取字符串中行数和列的最大字符数，返回两者的最大值
        row = words.count("\n") + 1

        # 存储所有的相同字符之间的距离
        length = []
        loc = 0
        last_loc = 0

        while words.find("\n", loc+1) != -1:
            loc = words.find("\n", loc+1)

            length.append(loc - last_loc)
            last_loc = loc

        length.append(len(words) - last_loc) # 获取最后一行长度
        # print(length)
        # print(f'最大长度：{max(length)}')
        column = max(length)
        # print(max(row, column))
        return max(row, column)

    def delete_files(file_path):
        if os.path.exists(file_path):
            shutil.rmtree(file_path)
            return True
        else:
            # file not found message
            print(f'要删除的文件夹{file_path}找不到')
            return False



class video_parse: # 视频处理
    def __init__(self, pro):
        self.pro = pro #项目名称
        self.subject = "" # 主题
        self.pro_path = "" # 处理的文件路径
        self.totle_time = "" # 总时长 以文字为准
        self.mp3_time = ""  # 音乐时间
        self.word = "" # 文字内容
        self.pic_num = "" # 图片数量

    def jianying_init(pro_path):  # 软件打开 将mp4导入并生成字幕 pro_path是文件夹
        time.sleep(1)
        file_path = pro_path

        pyautogui.hotkey('win', 'd') #先清空屏幕
        os.startfile(jianying_exe_path)
        time.sleep(3)

        gui.move_click(1100, 350, 3) #开始创作
        time.sleep(2)
        pyautogui.hotkey('ctrl', 'i') #导入素材 快捷键 ctrl I

        gui.move_click(1652, 67, 1)  # 查找文件路路径

        pyperclip.copy(file_path)  # 填入文件路径
        pyautogui.hotkey('ctrl', 'v')
        pyautogui.press('enter')
        gui.move_click(1652, 600)  # 移动到文件框空白处
        pyautogui.hotkey('ctrl', 'a')
        gui.move_click(1971, 1295)  # 点击导入

        gui.move_click(336, 328)  # 点加号
        # #将视频加入轨道 这里只有一个文件 但是选不准 只能拖
        if PC_COM == 0:
            gui.dragTo(388, 1076) # 拖拽过去

        gui.move_click(247, 107) # 点文本
        if PC_COM == 1:
            gui.move_click(92, 507)  # 点字幕
            gui.move_click(300, 419)  # 进行字幕生成
            gui.check_completed(1123, 798, 41, 41, 45)
        else:
            gui.move_click(103, 560) # 点字幕
            gui.move_click(303, 505) # 进行字幕生成
            # 一直等待生成完成 判断682 291 的rgb是不是变化
            gui.check_completed(1118, 531)


        print("转换完成")

        # x, y = pyautogui.size()
        # print(x, y) # 获取屏幕分辨率
        # x, y = pyautogui.position()
        # print(x, y)

        # pyautogui.moveTo(100, 200)  # 将鼠标移动至（100，200）坐标处
        # pyautogui.moveTo(1886, 17, 1) # 该移动过程是一个持续性过程，耗时 1 秒
        # pyautogui.move(0, 50, 1) # 将鼠标向下移动 50 像素
        # pyautogui.move(-30, 0, 1)  # 将鼠标向左移动 30 像素
        # pyautogui.dragTo(1886, 200, 1, button='left') # 按住鼠标左键将目标拖拽至坐标处 耗时 1 秒
        # pyautogui.drag(300, 0, 1, button='right') # 按住鼠标右键将目标向右移动 30 个像素，该移动过程是一个持续性过程，耗时 1 秒
        # pyautogui.press('enter') # 按下 enter / F1 键
        # pyautogui.press('f1')
        # pyautogui.click() # 在当前位置单击左键
        # pyautogui.doubleClick() # 在当前位置双击左键
        # pyautogui.write('Hello world!') # 输入 “Hello World”
        # pyautogui.hotkey('command', 'a')# 组合按键 command + a
        # time.sleep(0.5)


    def srt_save(titel, out_path):  # 标题不能超过20个字 返回保存路径 需要将成片文件剪切到草稿文件夹 未找到文件返回空路径
        gui.move_click(2022, 22)  # 点击导出
        if PC_COM == 1:
            gui.move_click(1438, 273)  # 点击作品名称
        else:
            gui.move_click(1500, 182)  # 点击作品名称

        # gui.move_click(1652, 67, 1)
        pyautogui.hotkey('ctrl', 'a')
        pyperclip.copy(titel + "-cut")
        pyautogui.hotkey('ctrl', 'v')

        # 选择导出路径
        if PC_COM == 1:
            gui.move_click(1557, 328)  # 点击作品路径
        else:
            gui.move_click(1603, 248)  # 点击作品路径
        print_d(out_path)
        pyperclip.copy(out_path)
        pyautogui.hotkey('ctrl', 'v')
        pyautogui.press('enter')
        gui.move_click(1954, 1290)  # 点击选择文件夹

        if PC_COM == 1:
            gui.move_click(1405, 1124) # 点击导出
        else:
            gui.move_click(1383, 1229)  # old 844 674
        # time.sleep(2) # 延时等待处理
        gui.move_click(1016, 781)  # 点击确认（有可能会出现文件已存在情况，替换）

        # 一直等待导出完成 判断1489 945 的rgb是不是变化 不考虑导出失败情况
        if PC_COM == 1:
            gui.check_completed(1489, 945)
        else:
            gui.check_completed(1292, 1040)  # old 788 570

        gui.move_click(1508, 1050)  # 点击关闭发布
        gui.move_click(2208, 34)  # 点击退出程序
        os.system("taskkill /F /IM JianyingPro.exe")  # 用python彻底关闭软件

    def pro_after_save(titel, out_path):  # 保存之后的操作
        new_build_path = os.path.join(out_path, (titel + "-cut"))
        print_d(new_build_path)
        folder = os.path.exists(new_build_path)
        if not folder:  # 判断是否存在文件夹, 如果不存在认为没有识别到声音 删除生成的新文件
            cut_file = doc_function.search_file("cut", out_path)[0]
            print("未识别到字幕，即将删除cut文件")
            os.remove(cut_file)
        else:  # 如果有新文件夹生成
            if doc_function.search_file(".srt", new_build_path) != None:  # 如果在新创建路径找到srt文件，则把原mp4文件后缀改为m4a
                old_name = out_path + "\\" + titel + '.mp4'
                os.remove(old_name)  # 删除源文件
                doc_function.remove_file(new_build_path, out_path)# 移动文件到上级路径
                shutil.rmtree(new_build_path)  # 删除子文件夹
                print("文件路径重规划成功")
            else:  # 如果没找到，则删除此新文件夹
                shutil.rmtree(new_build_path)
                print("删除剪映文件夹", new_build_path)

    def creat_srt(mp4_path):  # 创建srt字幕文件 生成的文件仍然在mp4文件所在路径
        for mp4 in mp4_path:
            f_mp4_path, f_mp4_name = os.path.split(mp4)
            print("即将操作", f_mp4_name)
            video_parse.jianying_init(f_mp4_path)  # 打开软件 将mp4导入并生成字幕
            video_parse.srt_save(f_mp4_name[:-4], f_mp4_path)  # 以mp4名字保存
            time.sleep(2)
            video_parse.pro_after_save(f_mp4_name[:-4], f_mp4_path)  # 保存之后的收尾操作

            break



class py_gui:
    def __init__(self):  # 不同电脑的gui坐标值不一样
        if PC_COM == 1:
            pyautogui.PAUSE = 0.5 # 所有操作暂停0.5s
        else:  # old pc
            pyautogui.PAUSE = 1  # 所有操作暂停

        self.dpi_x = pyautogui.size()[0]  # 长 默认2240
        self.dpi_y = pyautogui.size()[1]  # 高 默认1400

        self.x_radio = self.dpi_x/2240  # 自动进行坐标换算
        self.y_radio = self.dpi_y/1400

    def click(time_s = None):
        if time_s != None:
            time.sleep(time_s)
        pyautogui.click()

    def doubleClick(time_s = None):
        if time_s != None:
            time.sleep(time_s)
        pyautogui.doubleClick()


    def move_click(self, x, y, time_s = None):  # 鼠标移动到位置延时点击
        x = int((x) * (self.x_radio))
        y = int((y) * (self.y_radio))
        print(x, y)

        pyautogui.moveTo(x, y)
        py_gui.click(time_s)

    def dragTo(self, x, y):  # 默认左键拖拽
        x = int((x) * (self.x_radio))
        y = int((y) * (self.y_radio))

        pyautogui.dragTo(x, y, 1, button="left")

    def check_completed(self, x, y, r=None, g=None, b=None): # 判断是否完成某项内容 检测某个点的rgb值，如果rgb变化了认为有动作  或者如果符合rgb的值认为成功
        # 一直等待生成完成 判断x y 的rgb是不是r g b （识别中） 不考虑识别失败情况
        x = int((x) * (self.x_radio))
        y = int((y) * (self.y_radio))

        pyautogui.moveTo(x, y)
        rgb = pyautogui.screenshot().getpixel((x, y))
        r_last = rgb[0]
        g_last = rgb[1]
        b_last = rgb[2]
        time.sleep(1)

        if r == None or g == None or b == None: # 有一点像素变化认为完成
            while rgb[0] == r_last and rgb[1] == g_last and rgb[2] == b_last:  # 没有颜色变化
                rgb = pyautogui.screenshot().getpixel((x, y))
                posi = 'x:' + str(x).rjust(4) + ' y:' + str(y).rjust(4) + '  RGB:' + str(rgb)
                print("等待···", posi)
                time.sleep(1)
            print("发现颜色变化")
        else: # 符合rgb认为完成
            while rgb[0] != r and rgb[1] != g and rgb[2] != b:  # 没有出现符合的颜色
                rgb = pyautogui.screenshot().getpixel((x, y))
                posi = 'x:' + str(x).rjust(4) + ' y:' + str(y).rjust(4) + '  RGB:' + str(rgb)
                print("等待···", posi)
                time.sleep(1)
            print("发现符合的颜色")



if __name__ == "__main__":
    print("开始生成字幕及相关操作 !!!!")
    gui = py_gui()
    doc_function.sort_build_path()
    mp4_path = doc_function.search_no_srt_mp4()
    video_parse.creat_srt(mp4_path)
